/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package commands;

import SRDException.SRDException;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;
import protocol.*;

/**
 *
 * @author ylopez
 */
public class dcliComandos {

    public static String[] ldir(String path){
        File dir = new File(path);
        File[] ficheros = dir.listFiles();
        int i = 0;
        String[] archivos = null;

        if(ficheros==null){
            System.out.println("No hay ficheros en el directorio especificado \n"+path);
        }else {
            archivos = new String[2*ficheros.length];
            while(i<ficheros.length){
                archivos[2*i] = ficheros[i].getName();
                archivos[2*i+1] = Long.toString(ficheros[i].length());
                i++;
            }
        }
        return archivos;
    }

    public static String[] rdir(PrintWriter out, BufferedReader in){
        SRDProtocol srdpOut = new SRDProtocol("rdir", null);
        SRDProtocol srdpIn = new SRDProtocol();
        String messageFromServer = null;
        String[] resoult;
        
        out.println(srdpOut.getMessage());
        while (true) {
            try {
                if ((messageFromServer = in.readLine()) != null) {
                    break;
                }
            } catch (IOException ex) {
                Logger.getLogger(dcliComandos.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        srdpIn.setMessage(messageFromServer);
        resoult = srdpIn.processMessage();

        return resoult;
    }

    public static String[] tuser(PrintWriter out, BufferedReader in){
        SRDProtocol srdpOut = new SRDProtocol("tuser", null);
        SRDProtocol srdpIn = new SRDProtocol();
        String messageFromServer = null;
        String[] resoult;

        out.println(srdpOut.getMessage());
        while (true) {
            try {
                if ((messageFromServer = in.readLine()) != null) {
                    break;
                }
            } catch (IOException ex) {
                Logger.getLogger(dcliComandos.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        srdpIn.setMessage(messageFromServer);
        resoult = srdpIn.processMessage();

        return resoult;
    }

    public static String[] nrep(PrintWriter out, BufferedReader in){
        SRDProtocol srdpOut = new SRDProtocol("nrep", null);
        SRDProtocol srdpIn = new SRDProtocol();
        String messageFromServer = null;
        String[] resoult;

        out.println(srdpOut.getMessage());
        while (true) {
            try {
                if ((messageFromServer = in.readLine()) != null) {
                    break;
                }
            } catch (IOException ex) {
                Logger.getLogger(dcliComandos.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        srdpIn.setMessage(messageFromServer);
        resoult = srdpIn.processMessage();

        return resoult;
    }

    /**Crea una copia del archivo con nombre file del cliente en el directorio
 * dir del servidor
 *
 * @param file nombre del archivo a subir
 * @param out mensaje de solicitud del cliente al servidor
 * @param in mensaje de entrada recibido desde el protocolo
 * @param dir directorio donde se debe colocar la copia del archivo
 * @return content contenido del archivo a subir
 */
    public static String[] sube(String fileName, PrintWriter out, BufferedReader in, String directory, Socket socket){
        String[] result;
        File file = new File (directory + "/" +fileName);
        if (file.exists()) {
            String fileSize = String.valueOf((int)file.length());
            SRDProtocol srdpOut = new SRDProtocol("sube", new String[]{fileName,fileSize});
            out.println(srdpOut.getMessage());
            sendFile(fileName, directory, socket);
            SRDProtocol srdpIn = new SRDProtocol();
            String messageFromServer = null;

            
            while (true) {
                try {
                    if ((messageFromServer = in.readLine()) != null) {
                        break;
                    }
                } catch (IOException ex) {
                    Logger.getLogger(dcliComandos.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
            srdpIn.setMessage(messageFromServer);
            result = srdpIn.processMessage();
        } else {
            result = new String[]{"archivo "+ fileName +" no encontrado"};
        }
        
        return result;
    }

    public static String[] baja(String file, PrintWriter out, BufferedReader in, String directory, Socket socket){
        String[] result = null;
        int fileSize = existFile(file, out, in);
        if (fileSize != 0) {
            InputStream is = null;
            try {
                SRDProtocol srdpOut = new SRDProtocol("baja", new String[]{file});
                String messageFromServer = null;
                out.println(srdpOut.getMessage());
                int bytesLeidos;
                int current = 0;
                byte[] buffer = new byte[fileSize];
                is = socket.getInputStream();
                FileOutputStream fos = new FileOutputStream(directory + "/" + file); //escritura archivo
                BufferedOutputStream bos = new BufferedOutputStream(fos);
                bytesLeidos = is.read(buffer, 0, buffer.length); //Se lee el archivo
                current = bytesLeidos;
                do {
                    bytesLeidos = is.read(buffer, current, buffer.length - current);
                    if (bytesLeidos >= 0) {
                        current += bytesLeidos;
                    }
                } while (fileSize > current);
                bos.write(buffer, 0, current);
                bos.flush();
                bos.close();

                result = new String[]{"OK"};
            } catch (IOException ex) {
                Logger.getLogger(dcliComandos.class.getName()).log(Level.SEVERE, null, ex);
            } finally {
//                try {
//                    is.close();
//                } catch (IOException ex) {
//                    Logger.getLogger(dcliComandos.class.getName()).log(Level.SEVERE, null, ex);
//                }
            }
        } else {
            result = new String[]{"archivo "+ file +" no encontrado"};
        }

        return result;
    }

    public static void cat(String file){
        try {
            FileReader fr;
            BufferedReader bf;
            String line = "";

            fr = new FileReader(file);
            bf = new BufferedReader(fr);
            System.out.println("Inicio ejecuci'on cat:");
            while ((line = bf.readLine())!=null) {
                System.out.print(line+"\n");
            }
            System.out.println("Final ejecuci'on cat\n");

        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public static void readCommandsFromFile(String file, String currentDirectory, PrintWriter out, BufferedReader in, Socket socket){
        try {
            FileReader fr;
            BufferedReader bf;
            String line = "";
            String[] command;
            String[] resoults;

            fr = new FileReader(file);
            bf = new BufferedReader(fr);
            
            while ((line = bf.readLine())!=null) {
                command = line.split(" ");
                if (command[0].equals("ldir")) {
                    resoults = ldir(currentDirectory);
                    printResoults("ldir", resoults);
                } else if (command[0].equals("rdir")) {
                    resoults = rdir(out, in);
                    printResoults("rdir", resoults);
                } else if (command[0].equals("tuser")) {
                    resoults = tuser(out, in);
                    printResoults("tuser", resoults);
                } else if (command[0].equals("nrep")) {
                    resoults = nrep(out, in);
                    printResoults("nrep", resoults);
                } else if (command[0].equals("sube")) {
                    resoults = dcliComandos.sube(command[1], out, in,currentDirectory, socket);
                } else if (command[0].equals("baja")) {
                    baja(command[1], out, in, currentDirectory, socket);
                } else if (command[0].equals("cat")) {
                    cat(command[1]);
                } else {
                    SRDException srde = new SRDException("Comando: " + command[0]
                            + " invalido.");
                    srde.printException();
                }
            }

            bf.close();
            fr.close();

        } catch (IOException ex) {
            String [] exceptionMessage = ex.getMessage().split(" ");
            String permissionDeniedMessage = exceptionMessage[1] + " " + exceptionMessage[2];
            if(permissionDeniedMessage.equals("(Permission denied)")){
                System.err.println("No tiene permiso de lectura para: " + exceptionMessage[0]);
            } else {
                ex.printStackTrace();
                System.exit(-1);
            }
        }
    }

    public static void connect(String[] parameter, PrintWriter out, BufferedReader in) throws SRDException{
        SRDProtocol srdpOut = new SRDProtocol("connection", parameter);
        SRDProtocol srdpIn = new SRDProtocol();
        String messageFromServer = null;
        String[] resoult;

        
        out.println(srdpOut.getMessage());

        while (true) {
            try {
                if ((messageFromServer = in.readLine()) != null) {
                    break;
                }
            } catch (IOException ex) {
                Logger.getLogger(dcliComandos.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
        srdpIn.setMessage(messageFromServer);
        resoult = srdpIn.processMessage();

        if (resoult[0].equals("OK")){
            srdpOut = new SRDProtocol("replyReplyConnection", null);
            out.println(srdpOut.getMessage());
        } else {
            throw new SRDException("Drep ha rechazado la conexi'on");
        }
    }

    public static void printResoults(String flag, String[] resoults){
        System.out.println("Inicio ejecuci'on "+ flag +":");
        if (flag.equals("ldir") || flag.equals("rdir") || flag.equals("tuser")) {
            for (int i = 0; i < resoults.length; i += 2) {
                System.out.println(resoults[i] + " " + resoults[i+1]);
            }
        }
        if (flag.equals("nrep")) {
            System.out.println("N'umero de repositorios: " + resoults[0]);
        }

        if (flag.equals("sube") || flag.equals("baja")) {
            System.out.println("Estatus de sube: " + resoults[0]);
        }
        System.out.println("Final ejecuci'on "+ flag +".");
    }

    public static void disconnect(PrintWriter out, BufferedReader in, String[] parameter){
        SRDProtocol srdpOut = new SRDProtocol("disconnect", parameter);
        out.println(srdpOut.getMessage());
        System.exit(1);
    }

    public static String[] setFile(String file){
        FileReader fr;
        BufferedReader bf;
        String line = "";
        String[] copy;
        File arch = new File(file);
        copy = new String[3];
        copy[0] = file;
        copy[1] = Long.toString(arch.length());

        try {
            fr = new FileReader(file);
            bf = new BufferedReader(fr);

            while ((line = bf.readLine())!=null) {
                if (copy[2] != null){
                    copy[2] = copy[2]+line+"finaldelinia";
                } else {
                    copy[2] = line+"finaldelinia";
                }
            }
//            copy[2] = copy[2].substring(0,copy[2].length()-2);
//            copy[2] = copy[2] + " ";
            bf.close();
            fr.close();


        } catch (IOException ex) {

        }
        return copy;
    }

    private static int existFile(String file, PrintWriter out, BufferedReader in) {
        int existFile = 0;
        String messageFromServer;
        String[] result;
        SRDProtocol srdpIn = new SRDProtocol();
        SRDProtocol srdpOut = new SRDProtocol("existFile", new String[]{file});

        out.println(srdpOut.getMessage());
            while (true) {
                try {
                    if ((messageFromServer = in.readLine()) != null) {
                        break;
                    }
                } catch (IOException ex) {
                    Logger.getLogger(dcliComandos.class.getName()).log(Level.SEVERE, null, ex);
                }
            }
        srdpIn.setMessage(messageFromServer);
        result = srdpIn.processMessage();

        if (result[0].equals("true")) {
            existFile = (int) (Long.parseLong(result[1]));
        }
        return existFile;
    }

    private static String[] saveFile(String[] file, String directory) {
        FileWriter copy = null;
        String[] result = null;
        //TODO verga del separador
         try{
            FileWriter fstream = new FileWriter(directory + "/" +file[0]);
            BufferedWriter out = new BufferedWriter(fstream);
            String[] text = file[2].split("finaldelinia");
            for(int i = 0; i < text.length; i++){
                out.write(text[i] + "\n");
            }
//            out.write(result[2]);
            //Close the output stream
            out.close();
        }catch (Exception e){//Catch exception if any
          System.err.println("Error: " + e.getMessage());
        }

        result = new String[]{"OK"};
        return result;
    }

    public static void sendFile(String fileName, String directory, Socket socket) {
        File file = new File (directory + "/" +fileName);

        if(file.exists()){
            FileInputStream fis = null;
            try {
                byte[] buffer = new byte[(int) file.length()];
                fis = new FileInputStream(file);
                BufferedInputStream bis = new BufferedInputStream(fis);
                try {
                    bis.read(buffer, 0, buffer.length); // Leer
                    OutputStream os = socket.getOutputStream();
                    os.write(buffer, 0, buffer.length); //escribir en el socket
//                    os.flush();
                } catch (IOException ex) {
                    Logger.getLogger(drepComandos.class.getName()).log(Level.SEVERE, null, ex);
                }
            } catch (FileNotFoundException ex) {
                Logger.getLogger(drepComandos.class.getName()).log(Level.SEVERE, null, ex);
            } finally {
//                try {
////                    fis.close();
//                } catch (IOException ex) {
//                    Logger.getLogger(drepComandos.class.getName()).log(Level.SEVERE, null, ex);
//                }
            }
        } else{
                System.out.println("No exite el archivo");
        }
    }
}
